package 排序算法.基数排序;

import 动态链表.LinkedList;

import java.util.Arrays;
import java.util.Random;

/**
 * 基数排序
 * 时间复杂度：O(n + m)
 * 空间复杂度：O(n + m)
 * 稳定
 */
public class RadixSort {
    public static void main(String[] args) {
        int[] arr = new int[10];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(1000);
        }

        radixSort(arr);

        System.out.println(Arrays.toString(arr));
    }

    public static void radixSort(int[] arr) {
        //找到数组中的最大的数字，并计算该数字的位数
        int max = findMax(arr);
        int radix = (max + "").length();
        //定义一个linkList长度为10的数组，并对其进行初始化,不初始化为null，当做队列来使用，顶部入队，底部出队
        LinkedList<Integer>[] lists = new LinkedList[10];
        for (int i = 0; i < lists.length; i++) {
            lists[i] = new LinkedList<>();
        }

        //遍历最大数字的位数，即是最外层要排序的次数
        for (int r = 1; r <= radix; r++) {
            //遍历数组中的每一个数字,得出该数字在当前r的位数，得出的位数即为桶（linkedList数组）中的下标，并把该元素入队
            for (int i = 0; i < arr.length; i++) {
                lists[getIndex(arr[i],r)].offer(arr[i]);
            }
            //定义一个元素数组的操作的下标
            int index = 0;

            for (int i = 0; i < lists.length; i++) {
                //循环遍历linkedList，只要该数组中的linkedList不为空,就出队一个元素到原始数组中，index++
                while (!lists[i].isEmpty()){
                    arr[index++] = lists[i].poll();
                }
            }
        }

    }

    private static int getIndex(int num, int r) {
        //获取num的第r位数的值ret，作为返回的桶（linklist数组）的下标
        int ret = 0;
        for (int i = 1; i <= r; i++) {
            //取余得最后一个数字
            ret = num % 10;
            //整除去除最后一位数字
            num /= 10;
        }
        return ret;
    }

    private static int findMax(int[] arr) {
        //遍历数组找到其中的最大值
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max){
                max = arr[i];
            }
        }
        return max;
    }
}
